package cn.song.freight.enums;

import lombok.Getter;

import java.util.HashMap;
import java.util.Map;

/**
 * 定价模型枚举
 * <pre>
 * 该枚举定义了系统支持的运费定价模型类型，用于替代硬编码的数字常量。
 * 
 * 支持的定价模型：
 * 1. 首重续重模式（FIRST_ADDITIONAL_WEIGHT）：传统的首重+续重增量计费方式
 *    - 适用场景：小件快递、标准包裹配送
 *    - 计算方式：首重费用 + 超出首重部分按续重单位向上取整计算
 * 
 * 2. 混合计费模式（WEIGHT_SEGMENT_HYBRID）：结合重量区间规则和首重续重的复合计费方式  
 *    - 适用场景：大宗货物、重货专线、特殊商品配送
 *    - 计算方式：优先匹配重量区间规则，无匹配时回退到首重续重模式
 * </pre>
 *
 * @author SongRenShuo
 * @version 3.0.0
 * @since 2025-08-28
 */
@Getter
public enum PricingModel {
    
    /**
     * 首重续重模式（模式1）
     * <p>
     * 使用传统的首重+续重增量定价方式：
     * - 包裹重量不超过首重限制时收取首重费用
     * - 超出首重部分按续重单位向上取整计算续重费用
     * - 最终运费 = 首重费用 + 续重数量 × 续重单价
     */
    FIRST_ADDITIONAL_WEIGHT(1, "首重续重", "传统的首重+续重增量定价模式"),
    
    /**
     * 混合计费模式（模式2）
     * <p>
     * 结合重量区间规则和首重续重的复合定价方式：
     * - 优先根据计费重量匹配重量区间规则
     * - 如果匹配到区间规则，使用区间内的固定费用
     * - 如果无匹配的区间规则，回退到首重续重模式计算
     * - 适用于需要对特定重量范围进行差异化定价的场景
     */
    WEIGHT_SEGMENT_HYBRID(2, "混合计费", "重量区间规则+首重续重的复合定价模式");
    
    /**
     * 定价模型的数值代码
     */
    private final Integer code;
    
    /**
     * 定价模型的简短名称
     */
    private final String name;
    
    /**
     * 定价模型的详细描述
     */
    private final String description;
    
    /**
     * 代码到名称的映射缓存
     */
    private static final Map<Integer, String> CODE_TO_NAME_MAP = new HashMap<>();
    
    /**
     * 名称到代码的映射缓存
     */
    private static final Map<String, Integer> NAME_TO_CODE_MAP = new HashMap<>();
    
    /**
     * 构造函数
     *
     * @param code 数值代码
     * @param name 简短名称
     * @param description 详细描述
     */
    PricingModel(Integer code, String name, String description) {
        this.code = code;
        this.name = name;
        this.description = description;
    }
    
    /**
     * 通过 code 获取 name
     *
     * @param code 定价模型的编码
     * @return 对应的名称
     */
    public static String getNameByCode(Integer code) {
        if (code == null) {
            return "未知";
        }
        // 缓存为空时，初始化缓存
        if (CODE_TO_NAME_MAP.isEmpty()) {
            for (PricingModel model : values()) {
                CODE_TO_NAME_MAP.put(model.getCode(), model.getName());
            }
        }
        return CODE_TO_NAME_MAP.getOrDefault(code, "未知");
    }

    /**
     * 通过 name 获取 code
     *
     * @param name 定价模型的名称
     * @return 对应的code
     */
    public static Integer getCodeByName(String name) {
        if (name == null) {
            return 0;
        }
        // 缓存为空时，初始化缓存
        if (NAME_TO_CODE_MAP.isEmpty()) {
            for (PricingModel model : values()) {
                NAME_TO_CODE_MAP.put(model.getName(), model.getCode());
            }
        }
        return NAME_TO_CODE_MAP.getOrDefault(name, 0);
    }
    
    /**
     * 根据数值代码查找对应的定价模型枚举
     *
     * @param code 数值代码
     * @return 对应的枚举值
     * @throws IllegalArgumentException 当代码无效时抛出
     */
    public static PricingModel fromCode(Integer code) {
        if (code == null) {
            throw new IllegalArgumentException("定价模型代码不能为null");
        }
        for (PricingModel model : values()) {
            if (model.code.equals(code)) {
                return model;
            }
        }
        throw new IllegalArgumentException("不支持的定价模型代码: " + code);
    }
    
    /**
     * 根据数值代码查找对应的定价模型枚举（安全版本）
     *
     * @param code 数值代码
     * @return 对应的枚举值，如果未找到则返回null
     */
    public static PricingModel fromCodeSafe(Integer code) {
        if (code == null) {
            return null;
        }
        for (PricingModel model : values()) {
            if (model.code.equals(code)) {
                return model;
            }
        }
        return null;
    }
    
    /**
     * 检查指定的代码是否为有效的定价模型
     *
     * @param code 要检查的代码
     * @return 如果代码有效返回true，否则返回false
     */
    public static boolean isValidCode(Integer code) {
        return fromCodeSafe(code) != null;
    }
    
    @Override
    public String toString() {
        return String.format("PricingModel{code=%d, name='%s', description='%s'}", 
                code, name, description);
    }
}